home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / SCRIPT.PAK / TEMPLATE.SPP < prev    next >
Text File  |  1997-05-06  |  20KB  |  667 lines

  1. //----------------------------------------------------------------------------
  2. // cScript
  3. // (C) Copyright 1995, 1997 by Borland International, All Rights Reserved
  4. //
  5. // TEMPLATE.SPP
  6. //    Script component of IDE's Editor Template Editing.
  7. //    Provides support services for smart and template editing.
  8. //
  9. // $Revision:   1.4  $
  10. //
  11. //----------------------------------------------------------------------------
  12. // Template.spp
  13. //
  14. // This template class is enabled by simply loading the script file.
  15. // To enable this feature during every use of the IDE place the 
  16. // TEMPLATE.SPP file into the startup scipts in the 
  17. //
  18. //   Options | Environment | Scripting  Startup Scripts edit control
  19. //
  20. // Provided is a template description file for files with the extension of 
  21. // "c,cpp,h,hpp,spp" named c.tpl.  This file is located in the scripts 
  22. // subdirectory.  In the template editing class the template description 
  23. // file is assigned to extensions in the aExtensions array.  Each element 
  24. // of the array first specifies the extensions that the description file 
  25. // will be used for.  Next the description file is specified.  The 
  26. // convention is to name the file "something.tpl" where tpl stands for 
  27. // template.
  28. // 
  29. // While editing the template activation occurs by entering any number of 
  30. // characters within the keyword and then hitting the space bar the number
  31. // of times specified in the nTemplateActivation variable.  The default is
  32. // 1.  So if you type b and then hit the spacebar the b will be expanded to
  33. // break.  If the nTemplateActivate variable is 0 then the activation will
  34. // occur when the tab key is pressed.  Therefore as in the previous example
  35. // typing b then hitting the tab will cause the b to be expanded to break.
  36. //
  37. // Within the .tpl file is a keyword followed by the template command.  
  38. // The template command is made up of a series of numbers each specifying a 
  39. // template command.  For example the first line specifies the keyword 
  40. // "break" (without the quotes). The template command on the following 
  41. // line is: 
  42. //
  43. //   7 6 break;3 8 4 
  44. //
  45. // The format of the commands are two characters specifying the command.  
  46. // Some commands also accept numeric and alpha numeric arguments.  Below is 
  47. // a list of defines specifying the current list of template commands.  When
  48. // a template command has been recognized the text which triggered the 
  49. // command is removed then the command is processed.  
  50. //
  51. // We can decifer the template command string above by looking at the first 
  52. // command "7 "  (The space is important).  The 7 is defined as TEC_INSERT, 
  53. // this command inserts text.  The TEC_INSERT command accepts two arguments 
  54. // as seen below.  The first specifies the number of characters to insert 
  55. // then the actual characters follow.  So here it is saying that 6 characters
  56. // should be inserted and those six characters are "break;" (not including 
  57. // the quotes.  Again note that there is a space which follows the 6.  This
  58. // allows up to two digit arguments.  We can specify up to 99 allowing
  59. // for very large inserts.  Next there is a 3 which is TEC_AUTOINDENT this
  60. // command performs the same action as if you press the enter key.  In the
  61. // editor.  TEC_AUTOINDENT doesn't accept any arguments.  The cursors postion
  62. // is now moved to below the break;.  In the following the * represents the 
  63. // cursor position:
  64. //
  65. // Step 1, "b" is typed:
  66. //
  67. //     b*
  68. // 
  69. // Step 2, the space bar is hit and the TEC_INSERT command is executed:
  70. //
  71. //     break;*
  72. //
  73. // Step 3, the TEC_AUTOINDENT is executed:
  74. //
  75. //     break;
  76. //     *
  77. //
  78. // Next the 8 represents the TEC_OUTDENT command which moves the cursor
  79. // out (to the left) by one indent level.  Now the cursor is positioned 
  80. // to allow the next case statement to occur.
  81. //
  82. // Step 4, the TEC_OUTDENT is executed:
  83. //
  84. //     break;
  85. //  *
  86. //
  87. // Finally the 4 represents the TEC_GETCURSOR.  This command records the
  88. // row and column of the cursor.  At the end of each command string the 
  89. // cursor is placed at the internally recorded row and column.  This allows
  90. // for the placement of the cursor within the middle of the command.  For
  91. // example the switch command string is:
  92. //
  93. //   7 8 switch (4 7 1 )3 6 7 1 {3 3 7 1 }
  94. //
  95. // Note the 4 following the "(" after the switch text.  When the 
  96. // command sequence is completed the cursor will be positioned at that point.
  97. // So if you type s and hit the space bar the following expansion will occur
  98. // with the * representing the cursor position:
  99. //
  100. //   switch(*)
  101. //      {
  102. //
  103. //      }
  104. // 
  105. // Each command has a two character length allowing for up to 99 commands.
  106. // To add a command simply add a new case to the switch within the 
  107. // ExpansionServices method.  Examine the existing commands for examples of
  108. // argument parsing.
  109. //
  110. //----------------------------------------------------------------------------
  111. // Template Editing Command Reference.
  112. //----------------------------------------------------------------------------
  113. //
  114. // TEC_NULL 
  115. //    This command does nothing.
  116. //
  117. //    Arguments: None
  118. //
  119. // TEC_ALIGNIN
  120. //    This command positions the cursor to the right at the position in which
  121. //    on the first previous line a character is present. i.e.
  122. //
  123. //           This is line 1.
  124. //                *
  125. //
  126. //    If the cursor (specified by the asterisk) was below the 'i' in "is" 
  127. //    when this command executed the cursor would position under the 'l' in 
  128. //    "line".
  129. // 
  130. //    Arguments: None.
  131. //
  132. // TEC_AUTOINDENT
  133. //    This command is the equivlent of pressing the enter key and having
  134. //    the cursor position at the begining of the characters on the previous
  135. //    line.
  136. // 
  137. //    Arguments: None.
  138. //
  139. // TEC_CURSORGET
  140. //    This command records the current cursor row and column in the internal
  141. //     row and column variables.  The cursor will be returned to this 
  142. //     position at the termination of the command sequence.
  143. // 
  144. //    Arguments: None.
  145. //
  146. // TEC_CURSORSET
  147. //    This command set the cursor to the currently recorded row and column
  148. //    variables.
  149. // 
  150. //    Arguments: None. 
  151. //
  152. // TEC_INDENT
  153. //    This command moves the cursor to the right by one indent level.
  154. // 
  155. //    Arguments: None.
  156. //
  157. // TEC_INSERT
  158. //    This command inserts the specified text at the current cursor
  159. //    location.
  160. // 
  161. //    Arguments: 
  162. //      1) XX Number of characters to insert.
  163. //      2) The characters to insert.
  164. //
  165. // TEC_OUTDENT
  166. //    This command moves the cursor to the left by one indent level.
  167. // 
  168. //    Arguments: None.
  169. //
  170. //----------------------------------------------------------------------------
  171. import IDE;
  172. import editor;
  173. import scriptEngine;
  174.  
  175. // Template Editing Commands.
  176.  
  177. #define TEC_NULL       0
  178. #define TEC_ALIGNIN    1
  179. #define TEC_AUTOINDENT 3
  180. #define TEC_CURSORGET  4
  181. #define TEC_CURSORSET  5
  182. #define TEC_INDENT     6
  183. #define TEC_INSERT     7
  184. #define TEC_OUTDENT    8
  185.  
  186. class TemplateEditing
  187. {
  188.  // ---------------------------------------------------------------------------
  189.  // Variables
  190.  // ---------------------------------------------------------------------------
  191.  
  192.  // Local processing variables.
  193.  declare km = IDE.KeyboardManager;
  194.  declare bHooked = false;
  195.  declare bActivated = false;
  196.  
  197.  // Option Settings.
  198.  declare nTemplateActivation = 1;
  199.  
  200.  // Expansion variables.
  201.  declare array aExtensions[] = {
  202.                                 {"c,cpp,h,hpp,spp", "c.tpl" }
  203.                                };
  204.  declare nExpansions = 0;
  205.  declare aExpansions = new array[];
  206.  declare acExpansionFile = "";
  207.  declare nExpandableWord = 0;
  208.  declare nExpandableBrace = 0;
  209.  declare sExpandableWord = NULL;
  210.  
  211.  // Method tracking.
  212.  declare mOriginalTab = NULL;
  213.  declare mOriginalBrace = NULL;
  214.  declare mOriginalEnter = NULL;
  215.  declare mOriginalSpacebar = NULL;
  216.  
  217.  // Position tracking/counting.
  218.  declare nRow = 0;
  219.  declare nColumn = 0;
  220.  declare nSpaceCount = 0;
  221.  declare nKeysProcessed = 0;
  222.  
  223.  // ---------------------------------------------------------------------------
  224.  // Methods
  225.  // ---------------------------------------------------------------------------
  226.                                                                                
  227.  // Turn on template editing.
  228.  AtivateTemplateEditing() { bActivated = true; }
  229.  
  230.  // Turn off template editing.
  231.  DeactivateTemplateEditing() { bActivated = false; }
  232.  
  233.  // true == continuous keys. 
  234.  AreKeysContinuous()
  235.  {
  236.   if (km.KeysProcessed == nKeysProcessed + 1)
  237.      {
  238.       nSpaceCount++;
  239.       nKeysProcessed = km.KeysProcessed;
  240.       return true;
  241.      }
  242.   else
  243.      {
  244.       nSpaceCount++;
  245.       nKeysProcessed = km.KeysProcessed;
  246.       return false; 
  247.      }
  248.  }
  249.  
  250.  // Hook needed events/methods for template editing.
  251.  AttachTemplateEditing()
  252.  {
  253.  //Needtobackup
  254.   declare kbd = km.GetKeyboard("Editor");
  255.  
  256.   if (!bHooked) 
  257.      {
  258.       bHooked = true;
  259.       
  260.       if (nTemplateActivation != 0)
  261.          {
  262.           mOriginalSpacebar = kbd.GetCommand("<Space>");
  263.           kbd.Assign("<Space>","te.KeyProcessSpace();");
  264.          }
  265.       else
  266.          {
  267.           mOriginalTab = kbd.GetCommand("<Tab>");
  268.           kbd.Assign("<Tab>","te.KeyProcessTab();");
  269.          }
  270.  
  271.       mOriginalEnter = kbd.GetCommand("<Enter>");
  272.       kbd.Assign("<Enter>","te.KeyProcessEnter();");
  273.          
  274.       mOriginalBrace = kbd.GetCommand("<{>");
  275.       kbd.Assign("<{>","te.KeyProcessBrace();");
  276.      }
  277.  }
  278.  
  279.  // Unhook needed events/methods for template editing.
  280.  DetachTemplateEditing()                            
  281.  {
  282.   declare kbd = km.GetKeyboard("Editor");
  283.   
  284.   if (bHooked)
  285.      {
  286.       bHooked = false;
  287.       
  288.       if (mOriginalTab != NULL)
  289.          {
  290.           kbd.Assign("<Tab>",mOriginalTab);
  291.           mOriginalTab = NULL;
  292.          }
  293.          
  294.       if (mOriginalEnter != NULL)
  295.          {
  296.           kbd.Assign("<Enter>",mOriginalEnter);
  297.           mOriginalEnter = NULL;
  298.          }
  299.          
  300.       if (mOriginalSpacebar != NULL)
  301.          {
  302.           kbd.Assign("<Space>",mOriginalSpacebar);
  303.           mOriginalSpacebar = NULL;
  304.          }
  305.      }
  306.  }
  307.  
  308.  TimeForExpansion()
  309.  {
  310.   declare rv = false;
  311.   declare ep = editor.TopView.Position;
  312.                
  313.   if (!ep.IsWhiteSpace && ep.Character != 13)
  314.      return rv;
  315.   
  316.   declare nColumn = ep.Column;
  317.   ep.Save();
  318.   ep.MoveCursor(SKIP_RIGHT | SKIP_NONWORD);
  319.  
  320.   if (ep.Column == nColumn || ep.Character == 13)
  321.      rv = true;
  322.  
  323.   ep.Restore();
  324.  
  325.   ep.Save();
  326.  
  327.   ep.MoveCursor(SKIP_LEFT | SKIP_WHITE);
  328.  
  329.   ep.Restore();
  330.   
  331.   return rv;
  332.  }
  333.  
  334.  CheckForValidExpansion(declare nAdjustment)
  335.  {
  336.   declare ep = editor.TopView.Position;
  337.   
  338.   // Obtain an edit position.
  339.   declare nOriginalColumn = ep.Column;
  340.   
  341.   // Save the position.
  342.   ep.Save();
  343.  
  344.   // Move back onto the potential expanding item.
  345.   editor.MoveCursorToWordLeft();
  346.    
  347.   // Save our locality.
  348.   nRow = ep.Row;
  349.   nColumn = ep.Column;
  350.  
  351.   // Get the word.
  352.   sExpandableWord = new String("");
  353.   if (nOriginalColumn-nColumn > 0)
  354.       sExpandableWord = new String(ep.Read(nOriginalColumn-nColumn));
  355.  
  356.   // Restore the position.
  357.   ep.Restore();
  358.  
  359.   if (sExpandableWord.Text != "")
  360.      {
  361.       declare nIndex = 0;
  362.       for (nIndex=0;nIndex<nExpansions;nIndex++)
  363.          {
  364.           declare String sExpansion(aExpansions[nIndex][0]);
  365.  
  366.           if (sExpansion.SubString(0,sExpandableWord.Length).Text == sExpandableWord.Text)
  367.              {
  368.               nExpandableWord = nIndex;
  369.               return true;
  370.              }
  371.          }                                                                                
  372.      }
  373.   return false;
  374.  }
  375.  
  376.  ExpansionServices()
  377.  {
  378.   declare ep = editor.TopView.Position;
  379.   
  380.   // Go back to the begining of the word.
  381.   ep.Move(nRow,nColumn);
  382.   declare String sCommand(aExpansions[nExpandableWord][1]);
  383.   ep.Delete(sExpandableWord.Length);
  384.  
  385.   while (sCommand.Length)
  386.      {
  387.       switch (sCommand.Integer)
  388.          {
  389.           case TEC_ALIGNIN:
  390.              {
  391.               sCommand = sCommand.SubString(2);
  392.               ep.Align(1);
  393.               break;
  394.              }
  395.           case TEC_AUTOINDENT:
  396.              {
  397.               sCommand = sCommand.SubString(2);
  398.               ep.InsertCharacter('\r');
  399.               break;      
  400.              }
  401.           case TEC_CURSORSET:
  402.              {
  403.               sCommand = sCommand.SubString(2);
  404.               ep.Move(nRow, nColumn);
  405.               break;
  406.              }
  407.           case TEC_CURSORGET:
  408.              {
  409.               sCommand = sCommand.SubString(2);
  410.               nRow = ep.Row;
  411.               nColumn = ep.Column;
  412.               break;
  413.              }
  414.           case TEC_INDENT:
  415.              {
  416.               sCommand = sCommand.SubString(2);
  417.               ep.Tab(1);
  418.               break;
  419.              }
  420.           case TEC_INSERT:
  421.              {
  422.               // Strip off the command.
  423.               sCommand = sCommand.SubString(2);
  424.               declare nLength = sCommand.Integer;
  425.               ep.InsertText(sCommand.SubString(2,nLength).Text);
  426.               sCommand = sCommand.SubString(nLength+2);
  427.               break;
  428.              }
  429.           case TEC_OUTDENT:
  430.              {
  431.               sCommand = sCommand.SubString(2);
  432.               ep.Tab(-1);
  433.               break;      
  434.              }
  435.           default:
  436.               sCommand = sCommand.SubString(2);
  437.          }
  438.      } 
  439.   // Put the cusor at the defined location.
  440.   if (nRow && nColumn)
  441.       ep.Move(nRow,nColumn);
  442.  }
  443.  
  444.  KeyProcessBrace()
  445.  {
  446.   if (bActivated)
  447.      {
  448.       declare ep = editor.TopView.Position;
  449.  
  450.       ep.InsertText("{");
  451.     
  452.       nRow = ep.Row;
  453.       nColumn = ep.Column-1;
  454.  
  455.       if (!nColumn)
  456.          nColumn = 1;
  457.    
  458.       sExpandableWord = new String("{");
  459.       nExpandableWord = nExpandableBrace;
  460.  
  461.       return ExpansionServices();
  462.      }
  463.      
  464.   if (mOriginalBrace == NULL)
  465.      editor.TopView.Position.InsertCharacter('{');
  466.   else
  467.      scriptEngine.Execute(mOriginalBrace);
  468.  }
  469.  
  470.  KeyProcessEnter()
  471.  {
  472.   if (bActivated)
  473.      {
  474.       declare ep = editor.TopView.Position;
  475.  
  476.       ep.Save();
  477.       ep.MoveRelative(0,-1);
  478.       if (ep.Character != ';')
  479.          {
  480.           declare bIndent=true;
  481.           ep.MoveCursor(SKIP_LEFT|SKIP_WHITE);
  482.           if (ep.Column==1)
  483.             bIndent=false;
  484.          
  485.           ep.Restore();
  486.           ep.InsertCharacter('\r');
  487.           if (bIndent && ep.Column != 1)
  488.               ep.Tab(1);
  489.          }       
  490.       else
  491.          {
  492.           ep.Restore();
  493.           ep.InsertCharacter('\r');
  494.          }
  495.      }
  496.   else
  497.      {
  498.       if (mOriginalEnter == NULL)
  499.          editor.TopView.Position.InsertCharacter('\r');
  500.       else
  501.          scriptEngine.Execute(mOriginalEnter);
  502.      }
  503.  }    
  504.  
  505.  KeyProcessSpace()
  506.  {
  507.   if (bActivated)
  508.      {
  509.       if (TimeForExpansion())
  510.          {
  511.           // Space bar has been pressed.
  512.           if (nTemplateActivation > 1)
  513.              {
  514.               if (AreKeysContinuous())
  515.                  {
  516.                   if (nSpaceCount >= nTemplateActivation)
  517.                      {
  518.                       nSpaceCount = 0;
  519.                       
  520.                       // Adjust for multiple spacebar activation.
  521.                       declare ep = editor.TopView.Position;
  522.                       ep.MoveRelative(0,-(nTemplateActivation-1));
  523.  
  524.                       if (CheckForValidExpansion()) 
  525.                          {   
  526.                           // restore position...Delete extra spaces?? 
  527.                           ep.MoveRelative(0,nTemplateActivation-1);
  528.                           ep.BackspaceDelete(nTemplateActivation-1);
  529.                           return ExpansionServices();         
  530.                          }
  531.                      }  
  532.                  }
  533.              }
  534.           else
  535.              {
  536.               if (CheckForValidExpansion())
  537.                   return ExpansionServices();
  538.              }
  539.             }
  540.      }
  541.  
  542.   if (mOriginalSpacebar == NULL)
  543.      editor.TopView.Position.InsertCharacter(' ');
  544.   else
  545.      scriptEngine.Execute(mOriginalSpacebar);
  546.  }    
  547.  
  548.  KeyProcessTab()
  549.  {
  550.   if (bActivated)
  551.      if (TimeForExpansion())
  552.         if (CheckForValidExpansion())
  553.            return ExpansionServices();
  554.      
  555.   if (mOriginalTab == NULL)
  556.      editor.TopView.Position.InsertCharacter('\t');
  557.   else
  558.      scriptEngine.Execute(mOriginalTab);
  559.  } 
  560.  
  561.  
  562.  LoadExpansionFile(declare acFileName)
  563.  {
  564.   // Remove any old expansions.
  565.   nExpansions = 0;
  566.   nExpandableBrace = 0;
  567.   aExpansions = new array[];
  568.  
  569.   // Load and parse new expansion file.
  570.   declare ebExpansions = new EditBuffer(scriptEngine.StartupDirectory + acFileName, true);
  571.  
  572.   if (ebExpansions)
  573.      {
  574.       declare ep = ebExpansions.Position;
  575.       ep.Move(1,1);
  576.       declare nIndex;
  577.       declare acExpansionCommand;
  578.       for (nIndex=0;ep.Row<=ep.LastRow;nIndex++)
  579.           {
  580.           aExpansions[nIndex] = new array[2];
  581.           aExpansions[nIndex][0] = ep.Read();
  582.           if (ep.Character == '{')
  583.              nExpandableBrace = nIndex;
  584.           ep.MoveRelative(1,0);
  585.           ep.MoveBOL();
  586.           acExpansionCommand = new String(ep.Read());
  587.           acExpansionCommand = acExpansionCommand.Trim();
  588.           acExpansionCommand = acExpansionCommand.Text + " ";
  589.           aExpansions[nIndex][1] = acExpansionCommand;
  590.           ep.MoveRelative(1,0);        
  591.           ep.MoveBOL();
  592.           nExpansions++;
  593.          }
  594.      }
  595.   ebExpansions.Destroy();
  596.  }
  597. };
  598.  
  599. // Create instance of Template Editing object.
  600. export declare TemplateEditing te;
  601.  
  602. _init()
  603. {
  604.  te.LoadExpansionFile(te.aExtensions[0][1]);
  605.  te.AttachTemplateEditing();
  606.  print "Smart and template editing support loaded.";
  607. }
  608.  
  609. // First thing remove the attachements.
  610. on IDE:>KeyboardAssignmentsChanging(declare acNameOfKbdFile)
  611. {
  612.  te.DetachTemplateEditing();
  613.  pass(acNameOfKbdFile);
  614. }
  615.  
  616. // Last thing add the attachements.
  617. on IDE:>KeyboardAssignmentsChanged(declare acNameOfKbdFile)
  618. {
  619.  pass(acNameOfKbdFile);
  620.  te.AttachTemplateEditing();
  621. }
  622.  
  623. on editor:>ViewActivated(declare ev)
  624. {
  625.  te.DeactivateTemplateEditing();
  626.  pass(ev);         
  627.         
  628.  declare nIndex = 0;              
  629.  declare acExtension = new String(ev.Window.Title);
  630.  acExtension = acExtension.SubString(acExtension.Index(".",SEARCH_BACKWARD),3);
  631.  acExtension = acExtension.Lower();
  632.  acExtension = acExtension.Text;
  633.  
  634.  do {
  635.      declare String sExtensionList(te.aExtensions[nIndex][0]);
  636.      declare acExtensionList = "";
  637.    
  638.      while (sExtensionList != NULL)
  639.         {
  640.          acExtensionList = sExtensionList.SubString(0,sExtensionList.Index(",")-1).Text;
  641.          if (acExtensionList == acExtension) 
  642.             {
  643.              // Attach methods.
  644.              if (te.acExpansionFile != te.aExtensions[nIndex][1])
  645.                 {
  646.                  te.acExpansionFile = te.aExtensions[nIndex][1];
  647.                  te.LoadExpansionFile(te.aExtensions[nIndex][1]);
  648.                 }
  649.              te.AtivateTemplateEditing();
  650.              return; 
  651.             }
  652.          if (sExtensionList.Index(","))
  653.             sExtensionList = sExtensionList.SubString(sExtensionList.Index(","));
  654.          else
  655.             sExtensionList = NULL;
  656.         }                
  657.    nIndex++;
  658.  } while (initialized(te.aExtensions[nIndex]));
  659. }
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.  
  667.